#!/bin/bash
# cp-l: Determines if we are doing the cp job in the same fs.
# If so, add '-l' to cp.
# Arguments from cp (GNU coreutils) 8.23, therefore:
# @license GPL-3.0+
shopt -s extglob

declare -A mount_state
# initialization: mtab
while IFS=' ' read -r fs mpoint type opts dump pass; do
	# hey printf eat the escapes
	mpoint="$(printf %b- "${mpoint%/}")"
	mpoint="${mpoint%-}"
	# hey wut is dis
	# [[ $fs == *fs ]] || fs="$(readlink -e "$fs")"
	mount_state["$mpoint"]="${fs%/} $type $opts $dump $pass"
done < /etc/mtab

# argument processing
gopt="$(getopt -o abdfiHlLnPpRrsStTuvxZ \
--long archive,attributes-only,backup:,copy-contents,force,interactive,link,dereference,no-clobber,no-dereference,\
preserve:,no-preserve:,parents,recursive,reflink:,remove-destination,sparse:,strip-trailing-slashes,\
symbolic-link,suffix:,target-directory:,no-target-directory,update,verbose,one-file-system,context:,help,version \
-n "$0" -- "$@")" || exit $?
eval gopt="($gopt)"
gargc=${#gopt[@]}

target_is_dir=0
for ((f=0; f<gargc; f++)); do
	case "${gopt[f]}" in
		--)	break;;
		-t|--target-directory)			# target dir
			target_is_dir=1
			target="${gopt[f+1]}";;		# only consider last one
		--target-directory=*)			# ditto
			target_is_dir=1
			target="${gopt[f]#--target-directory=}";;
	esac
done

srcf=("${gopt[@]:f+1}")
gopt=("${gopt[@]:0:f}")
if [[ $target == '' ]]; then
	target=${srcf[-1]}
	unset srcf[-1]
fi

fs_name_maybe(){
	fs=$1
	fs=$(readlink -m "$f"; echo x) o=${ofx}
	fs=${f/#'//'+(/)/'/'}			# normalize abs path
	if [[ $fs == //* ]]; then		# don't do the stupid thing on //
		fs=//
		return
	fi
	local components=() IFS=/
	read -a components <<< "$fs"
	while ((${#components[@]})); do
		fs="${components[*]}"
		if [[ "${mount_state[$fs]}" != '' ]]; then
			return
		fi
		unset components[-1]
	done
	false
}

files_link=()
files_norm=()
fs_name_maybe "$target"		&&
target_fs=$fs			&& # if we fail target_fs, then it's pointless to do the check.

for f in "${srcf[@]}"; do
	if fs_name_maybe "$f"; then
		files_link+=("$f")
	else
		files_norm+=("$f")
	fi
done

# moral dilemma: should we try the linked cp first, or the normal cp first?
# go for the linked one.

if ((target_is_dir)); then
	gopt+=(--target-directory="$target")
else
	files_link+=("$target")
	files_norm+=("$target")
fi

# note: when target_is_dir=true; we cmp w/ 0; otherwise 1.
if ((${#files_link[@]} > (!target_is_dir) )); then
	cp "${gopt[@]}" --link -- "${files_link[@]}"
fi &&
if ((${#files_norm[@]} > (!target_is_dir) )); then
	cp "${gopt[@]}"        -- "${files_norm[@]}"
fi


